Skip to main content

A Way to Monitor Active Automations Status Using WSProxy

During my years working on Salesforce Marketing Cloud, I have made this mistake at least once on every particular project and there is a good chance you have done it too.

Have you ever wanted to check/edit an activity on Automation Studio? Sure, but did you use the Activities tab opened or did it directly on the active automation? See where is it going?

When we try to open an activity on an active automation, SFMC prompts the box below informing us that this action would pause the automation. The problem is, very often, after finishing the editing of the activity, we forget to activate the automation again.

Monitor automations with WSProxy

caution

This can have some serious problems on the functioning of an SFMC instance. Especially if it have automations that run frequently and export data that can not be recovered, for example, exporting the content of a DE that is overwritten on each running occurrence.

In this article, I will share with you a way to monitor active automations by checking a CloudPage that shows the current status of every automation that is supposed to be active at that specific moment. As a bonus, we can schedule an automation that runs daily and sends the list of those automations to a list of emails.

Overview of the solution

  • Create a data extension that contains our active automations names along with a boolean field called toBeMonitored
  • Create a CloudPage that shows active automations current status
  • A bonus

Create Automations Monitoring List Data Extension

The data extension will be named Automations_Monitoring_List. Basically, it will be populated once and then updated everytime we add/remove an automation on Automation Studio. It should contain all the automations that need to be Active. You can populate it manually, but if the SFMC instance is too big to do so, we can populate it automatically using SSJS/WSProxy. We can use some code snippets we have in this article to get the list of all automations names. The DE should look like this:

Field NameField TypeLength
AutomationNameText500
toBeMonitoredBoolean
CategoryText250
isActiveBoolen
info

The primary key is the AutomationName field.

We can disable monitoring on an automation by setting toBeMonitored to false.

The Category is optional if we want to sort automations.

I’ll explain how we can use the isActive field on the bonus part.

Create CloudPage to Monitor Active Automations

First of all, we need to do a lookup on Automations_Monitoring_List DE to get the list of automations that need to be monitored. The toBeMonitored field should be set to true.

We are looping through the retrieve results and calling the getAutomationStatus function to get the status of the automation.

Platform.Load("Core","1");

var api = new Script.Util.WSProxy();

try {
/* Retreive Automations_Monitoring_List DE automations that need to be monitored */
var deCustKey = 'Automations_Monitoring_List';

var cols = ["AutomationName", "toBeMonitored"];
var filter = {
Property: "toBeMonitored",
SimpleOperator: "equals",
Value: true
};

var deReturn = api.retrieve("DataExtensionObject[" + deCustKey + "]", cols, filter);
var automationName = "";
for (var a = 0; a < deReturn.Results.length; a++) {
var results = deReturn.Results[a];
for (var i = 0; i < results.Properties.length; i++) {
var value = results.Properties[i].Value;
if (results.Properties[i].Name == "AutomationName") {
Write(Stringify(value + " : "+ getAutomationStatus(results.Properties[i].Value) + " || "));
}

}
}
} catch(err) {
var error = {
Status: 500,
Message: err
}
Write(Stringify(error));
}

The code below shows how are we retrieving the automation status and calling our second function called getAutomationStatusNameto put a name on automations status codes. The status Ready or Running means that the automation is Active. If it’s the case, we return Active, otherwise, the actual status is returned.

/* Function to retrieve automation status */ 
function getAutomationStatus(automationName) {
var result = api.retrieve("Automation", ["Name","ProgramID","CustomerKey","Status"], {
Property: "Name",
SimpleOperator: "equals",
Value: automationName
});

var automation = result.Results[0];
var objectId = automation.ObjectID;
if(objectId == null) throw "No automation with the name \"" + automationName + "\" was found.";
else {
var status = getAutomationStatusName(automation.Status);
if(status == "Running" || status == "Ready") {
var response = "Active";
}
else var response = status;
}
return status;
}

/* Function to retrieve automation status based on returned status code - Thanks Ivan ;) */
function getAutomationStatusName(num) {
switch(num) {
case -1:
status = 'Error';
break;
case 0:
status = 'Building error';
break;
case 1:
status = 'Building';
break;
case 2:
status = 'Ready';
break;
case 3:
status = 'Running';
break;
case 4:
status = 'Paused';
break;
case 5:
status = 'Stopped';
break;
case 6:
status = 'Scheduled';
break;
case 7:
status = 'Awaiting trigger';
break;
case 8:
status = 'Inactive trigger';
break;
}
return status;
}

As you might have noticed, the UI is very basic. I’ll let you check my other article on how to Use Lightning Design System in CloudPages. You can personalize the UI with the look and feel of Lightning.

Full Code

<script runat='server'>
Platform.Load("Core","1");

var api = new Script.Util.WSProxy();

try {
/* Retreive Automations_Monitoring_List DE automations that need to be monitored */
var deCustKey = 'Automations_Monitoring_List';

var cols = ["AutomationName", "toBeMonitored"];
var filter = {
Property: "toBeMonitored",
SimpleOperator: "equals",
Value: true
};

var deReturn = api.retrieve("DataExtensionObject[" + deCustKey + "]", cols, filter);
var automationName = "";
for (var a = 0; a < deReturn.Results.length; a++) {
var results = deReturn.Results[a];
for (var i = 0; i < results.Properties.length; i++) {
var value = results.Properties[i].Value;
if (results.Properties[i].Name == "AutomationName") {
Write(Stringify(value + " : "+ getAutomationStatus(results.Properties[i].Value) + " || "));
}

}
}
} catch(err) {
var error = {
Status: 500,
Message: err
}
Write(Stringify(error));
}

/* Function to retrieve automation status */
function getAutomationStatus(automationName) {
var result = api.retrieve("Automation", ["Name","ProgramID","CustomerKey","Status"], {
Property: "Name",
SimpleOperator: "equals",
Value: automationName
});

var automation = result.Results[0];
var objectId = automation.ObjectID;
if(objectId == null) throw "No automation with the name \"" + automationName + "\" was found.";
else {
var status = getAutomationStatusName(automation.Status);
if(status == "Running" || status == "Ready") {
var response = "Active";
}
else var response = status;
}
return status;
}

/* Function to retrieve automation status based on returned status code - Thanks Ivan ;) */
function getAutomationStatusName(num) {
switch(num) {
case -1:
status = 'Error';
break;
case 0:
status = 'Building error';
break;
case 1:
status = 'Building';
break;
case 2:
status = 'Ready';
break;
case 3:
status = 'Running';
break;
case 4:
status = 'Paused';
break;
case 5:
status = 'Stopped';
break;
case 6:
status = 'Scheduled';
break;
case 7:
status = 'Awaiting trigger';
break;
case 8:
status = 'Inactive trigger';
break;
}
return status;
}
</script>

Bonus

If you want to go the extra mile, there are plenty of things you can add to this process. First, create a data extension with SubscriberKey and EmailAddress fields. Next, populate it with the list of contacts that need to be informed when something goes wrong. Make sure to keep it light.

Then, create a script activity in an automation that runs daily/hourly. The script should check the list of automations that need to be active and that are not, store this list in another DE called Automations_NotActive, send an email to the contacts data extension after doing a lookup on Automations_NotActive.

info

In this kind of articles, I try to give basic details about the solution. It's your job to adapt it to your use case and enhance it. After all, I believe that progress is made only by practicing.

Let me know if you have any questions. Cheers!